﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using YJKRGeometry;

namespace ModelCheckUtility.ModelLayer
{
	public class BaseAreaPacker : BaseElementPacker
	{
		public List<BaseDoorPacker> LstDoorPackerInThis
		{
			get
			{
				return this.m_lstDoorPackerInThis;
			}
		}

		public Level m_ThisLevel
		{
			get
			{
				return this.ThisLevel;
			}
		}

		public List<BaseRoomPacker> LstRoomPackerInThis
		{
			get
			{
				return this.m_lstRoomPackerInThis;
			}
		}

		public List<ICloseCurveAnalays> LstCloseCurvePackerInThis
		{
			get
			{
				return this.m_lstCloseCurvePackerInThis;
			}
		}

		public Area ThisArea
		{
			get
			{
				return this.m_thisArea;
			}
			private set
			{
				this.m_thisArea = value;
			}
		}

		public Level ThisLevel
		{
			get
			{
				return this.m_thisLevel;
			}
			private set
			{
				this.m_thisLevel = value;
			}
		}

		public BaseAreaPacker(Area inputElement, RevitLinkInstance useRevitLinkInstance = null, object[] otherValues = null) : base(inputElement, useRevitLinkInstance, otherValues)
		{
			this.ThisArea = inputElement;
			this.m_lstBoundCurves = new List<Curve>();
			if (this.ThisArea != null)
			{
				this.ThisLevel = this.ThisArea.Level;
			}
			this.m_lstDoorPackerInThis = new List<BaseDoorPacker>();
			this.m_lstRoomPackerInThis = new List<BaseRoomPacker>();
			this.m_lstCloseCurvePackerInThis = new List<ICloseCurveAnalays>();
			foreach (IList<BoundarySegment> list in inputElement.GetBoundarySegments(new SpatialElementBoundaryOptions()))
			{
				foreach (BoundarySegment boundarySegment in list)
				{
					if (boundarySegment != null && null != boundarySegment.GetCurve())
					{
						if (base.UseTransform == null)
						{
							this.m_lstBoundCurves.Add(boundarySegment.GetCurve());
						}
						else
						{
							this.m_lstBoundCurves.Add(boundarySegment.GetCurve().CreateTransformed(base.UseTransform));
						}
					}
				}
			}
		}

		public virtual void AddRoomPacker(BaseRoomPacker inputValue)
		{
			this.m_lstRoomPackerInThis.Add(inputValue);
			this.m_lstRoomPackerInThis = this.m_lstRoomPackerInThis.Distinct<BaseRoomPacker>().ToList<BaseRoomPacker>();
		}

		public virtual void AddDoorPacker(BaseDoorPacker inputValue)
		{
			this.m_lstDoorPackerInThis.Add(inputValue);
			this.m_lstDoorPackerInThis = this.m_lstDoorPackerInThis.Distinct<BaseDoorPacker>().ToList<BaseDoorPacker>();
		}

		public virtual void AddDoorPacker(List<BaseDoorPacker> inputValue)
		{
			this.m_lstDoorPackerInThis.AddRange(inputValue);
			this.m_lstDoorPackerInThis = this.m_lstDoorPackerInThis.Distinct<BaseDoorPacker>().ToList<BaseDoorPacker>();
		}

		public virtual void AddCloseCurveAnalaysPacker(ICloseCurveAnalays inputValue)
		{
			this.m_lstCloseCurvePackerInThis.Add(inputValue);
			this.m_lstCloseCurvePackerInThis = this.m_lstCloseCurvePackerInThis.Distinct<ICloseCurveAnalays>().ToList<ICloseCurveAnalays>();
		}

		public bool IfInThis(Element input)
		{
			if (input is Room)
			{
				return this.IfInThis(input as Room);
			}
			return input is FilledRegion && this.IfInThis(input as FilledRegion);
		}

		public bool IfInThis(XYZ input, bool ifmove = false)
		{
			XYZ pt = input;
			if (input == null)
			{
				return false;
			}
			if (ifmove)
			{
				pt = new XYZ(input.X, input.Y, this.ThisArea.Level.Elevation);
			}
			int num = Geometry.PointInPloygon(this.m_lstBoundCurves, pt);
			return 1 == num;
		}

		private bool IfInThis(FilledRegion input)
		{
			List<Curve> list = new List<Curve>();
			foreach (GeometryObject geometryObject in input.get_Geometry(new Options()))
			{
				Solid solid = (Solid)geometryObject;
				if (!(null == solid))
				{
					foreach (object obj in solid.Edges)
					{
						Edge edge = (Edge)obj;
						if (!(null == edge))
						{
							list.Add(edge.AsCurve());
						}
					}
				}
			}
			return this.IfInThis(Utility.CalculateLstCurveMidPoint(list), false);
		}

		private bool IfInThis(Room input)
		{
			return Geometry.IsEqual(input.Level.Elevation, this.ThisArea.Level.Elevation) && input.Location != null && this.IfInThis((input.Location as LocationPoint).Point, false);
		}

		private Area m_thisArea;

		private Level m_thisLevel;

		private List<Curve> m_lstBoundCurves;

		private List<BaseDoorPacker> m_lstDoorPackerInThis;

		private List<BaseRoomPacker> m_lstRoomPackerInThis;

		private List<ICloseCurveAnalays> m_lstCloseCurvePackerInThis;
	}
}
